import ctypes
import subprocess
import psutil
from app.controller import index
from app.controller import Install
from app.utils import Log
from app.utils import System
from app.utils import File
import os
import sys
from app.utils import WordsImg

LOCK_FILE = "running.lock"

ROOT_PATH = os.getcwd()
Log.New("----------------启动程序----------------")


# 检查权限
def check_permission():
    if System.get_system_name() == "Linux":
        if os.getuid() != 0:
            Log.New("exit: Use ROOT to run")
            print("请使用ROOT用户运行此程序")
    else:
        try:
            # 使用 ctypes.windll.shell32.IsUserAnAdmin 来检查当前用户是否是管理员
            if ctypes.windll.shell32.IsUserAnAdmin() == 0:
                Log.New("exit: Use Admin to run")
                sys.exit("请使用管理员用户运行此程序")
        except AttributeError:
            # 如果 IsUserAnAdmin 函数不可用，则当前系统不支持该方法，因此返回 False
            Log.New("exit: Use Admin to run")
            sys.exit("请使用管理员用户运行此程序")


# 工作函数
def main():
    if File.Had("data/config/panel.json"):
        print("欢迎使用QPanel服务器管理面板")
        check_permission()  # 检查权限
        print("正在启动面板...")
        Log.New("Start QPanel")
        print("------------------------------------")
        index.service_start(ROOT_PATH)
    else:
        print("未安装面板")
        check_permission()  # 检查权限
        input_install = input("是否安装面板(y/n):")
        if input_install == "y":
            # 安装面板
            print("开始安装面板...")
            if Install.PanelInstall(ROOT_PATH):
                print("安装成功")
                Log.New("Install True")
                # 获取当前可执行文件的路径
                executable = sys.executable
                if System.get_system_name() == "Linux":
                    input("请及时保留您的登录信息（按下任意键结束进程并重启）")
                else:
                    input("请及时保留您的登录信息（按下任意键结束进程并手动重启）")
                subprocess.Popen([executable] + sys.argv)

                # 退出当前程序
                sys.exit()
            else:
                Log.New("Install False")
                print("安装失败")
        else:
            print("退出程序")


if System.get_system_name() == "Windows":
    import win32file
    import win32con
    import pywintypes
    import winerror
    import sys

    class SingleInstanceGuardian:
        def __init__(self, lock_file_path):
            self._lock_file_path = lock_file_path
            self._lock_file = None

        def _acquire_lock(self):
            try:
                # 创建一个文件用于锁定
                self._lock_file = win32file.CreateFile(
                    self._lock_file_path,
                    win32file.GENERIC_WRITE,
                    0,
                    None,
                    win32file.CREATE_ALWAYS,
                    win32file.FILE_ATTRIBUTE_NORMAL,
                    None
                )
                # 尝试获取文件锁
                win32file.LockFileEx(self._lock_file,
                                     win32con.LOCKFILE_EXCLUSIVE_LOCK | win32con.LOCKFILE_FAIL_IMMEDIATELY, 0,
                                     -0x10000, pywintypes.OVERLAPPED())
                return True
            except pywintypes.error as e:
                if e.winerror == winerror.ERROR_LOCK_VIOLATION:
                    return False
                else:
                    raise

        def _release_lock(self):
            if self._lock_file:
                win32file.UnlockFileEx(self._lock_file, 0, -0x10000, pywintypes.OVERLAPPED())
                win32file.CloseHandle(self._lock_file)

        def is_already_running(self):
            return not self._acquire_lock()

        def run_task(self):
            main()

            # 任务完成后释放锁
            self._release_lock()


    # 使用示例
    lock_file_path = LOCK_FILE
    Log.New("Start File Lock")
    guardian = SingleInstanceGuardian(lock_file_path)
    guardian._release_lock()

if (len(sys.argv) > 1 and sys.argv[1] == "start") or len(sys.argv) == 1:
    # 启动程序

    if File.Had('./pid.txt'):
        pid = File.Read('./pid.txt')
        pid_info = System.get_process_info(int(pid))
        if pid_info:
            if pid_info["status"] == "running":
                print("程序已经在运行中")
                sys.exit(1)
    else:
        print("pid.txt 文件不存在")
    File.Write("./pid.txt", str(os.getpid()))
    # 写入进程号

    if System.get_system_name() == "Linux":
        import fcntl

        lockfile = open(LOCK_FILE, "w")
        try:
            fcntl.lockf(lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
        except IOError:
            print("程序已经在运行中")
            File.Del("./pid.txt")
            sys.exit(1)
        lockfile.close()
        os.unlink(LOCK_FILE)
        main()
    else:
        guardian.run_task()

elif len(sys.argv) > 1 and sys.argv[1] == "stop":
    # 停止程序
    print("stop")
    if System.get_system_name() == "Linux":
        if os.path.exists(LOCK_FILE):
            os.unlink(LOCK_FILE)
            if File.Had('./pid.txt'):
                pid = File.Read('./pid.txt')
                pid_info = System.get_process_info(int(pid))
                if pid_info != False:
                    if pid_info["status"] == "running":
                        print("程序已经在运行中")
                        os.kill(pid, 9)  # 9表示SIGKILL信号，强制终止进程
                        File.Del("./pid.txt")
                        print("关闭成功")

            print("停止程序")
        else:
            print("程序未在运行中")
    else:
        #  Windows
        if File.Had('./pid.txt'):
            pid = File.Read('./pid.txt')
            pid_info = System.get_process_info(int(pid))
            if pid_info:
                if pid_info["status"] == "running":
                    print("程序已经在运行中")
                    try:
                        # 根据进程ID获取进程对象
                        process = psutil.Process(int(pid))
                        # 终止进程
                        process.terminate()
                        File.Del("./pid.txt")
                        print("关闭成功")
                    except psutil.NoSuchProcess:
                        # 如果没有找到对应的进程，返回 False
                        print("关闭失败")

        guardian._release_lock()

elif len(sys.argv) > 1 and sys.argv[1] == "run":
    if System.get_system_name() == "Linux":
        subprocess.run(['bash', 'run.sh'])
    else:
        subprocess.run(['cscript', '//NoLogo', 'run.vbs'])
else:
    print("无效的命令")
